home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / internet / web-related / apache_1.0.5 / cgi-src / imagemap.c < prev    next >
Text File  |  1996-02-16  |  11KB  |  354 lines

  1. /*
  2. ** mapper 1.2
  3. ** 7/26/93 Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
  4. ** "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
  5. ** All suggestions, help, etc. gratefully accepted!
  6. **
  7. ** 1.1 : Better formatting, added better polygon code.
  8. ** 1.2 : Changed isname(), added config file specification.
  9. **
  10. ** 11/13/93: Rob McCool, robm@ncsa.uiuc.edu
  11. **
  12. ** 1.3 : Rewrote configuration stuff for NCSA /htbin script
  13. **
  14. ** 12/05/93: Rob McCool, robm@ncsa.uiuc.edu
  15. ** 
  16. ** 1.4 : Made CGI/1.0 compliant.
  17. **
  18. ** 06/27/94: Chris Hyams, cgh@rice.edu
  19. **          Based on an idea by Rick Troth (troth@rice.edu)
  20. ** 
  21. ** 1.5 : Imagemap configuration file in PATH_INFO.  Backwards compatible.
  22. **
  23. **  Old-style lookup in imagemap table:
  24. **    <a href="http://foo.edu/cgi-bin/imagemap/oldmap">
  25. **
  26. **  New-style specification of mapfile relative to DocumentRoot:
  27. **    <a href="http://foo.edu/cgi-bin/imagemap/path/for/new.map">
  28. **
  29. **  New-style specification of mapfile in user's public HTML directory:
  30. **    <a href="http://foo.edu/cgi-bin/imagemap/~username/path/for/new.map">
  31. **
  32. ** 07/11/94: Craig Milo Rogers, Rogers@ISI.Edu
  33. **
  34. ** 1.6 : Added "point" datatype: the nearest point wins.  Overrides "default".
  35. **
  36. ** 08/28/94: Carlos Varela, cvarela@ncsa.uiuc.edu
  37. **
  38. ** 1.7 : Fixed bug:  virtual URLs are now understood.
  39. **       Better error reporting when not able to open configuration file.
  40. **
  41. ** 03/07/95: Carlos Varela, cvarela@ncsa.uiuc.edu
  42. **
  43. ** 1.8 : Fixed bug (strcat->sprintf) when reporting error.
  44. **       Included getline() function from util.c in NCSA httpd distribution.
  45. **
  46. */
  47.  
  48. #include <stdio.h>
  49. #include <string.h>
  50. #ifndef pyr
  51. #include <stdlib.h>
  52. #else
  53. #include <ctype.h>
  54. #endif
  55. #include <sys/types.h>
  56. #include <sys/stat.h>
  57.  
  58. #define CONF_FILE "/usr/local/etc/httpd/conf/imagemap.conf"
  59.  
  60. #define MAXLINE 500
  61. #define MAXVERTS 100
  62. #define X 0
  63. #define Y 1
  64. #define LF 10
  65. #define CR 13
  66.  
  67. int isname(char);
  68.  
  69. int main(int argc, char **argv)
  70. {
  71.     char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE], errstr[MAXLINE];
  72.     double testpoint[2], pointarray[MAXVERTS][2];
  73.     int i, j, k;
  74.     FILE *fp;
  75.     char *t;
  76.     double dist, mindist;
  77.     int sawpoint = 0;
  78.     
  79.     if (argc != 2)
  80.         servererr("Wrong number of arguments, client may not support ISMAP.");
  81.     mapname=getenv("PATH_INFO");
  82.  
  83.     if((!mapname) || (!mapname[0]))
  84.         servererr("No map name given. Please read the <A HREF=\"http://hoohoo.ncsa.uiuc.edu/docs/setup/admin/Imagemap.html\">instructions</A>.<P>");
  85.  
  86.  
  87.     mapname++;
  88.     if(!(t = strchr(argv[1],',')))
  89.         servererr("Your client doesn't support image mapping properly.");
  90.     *t++ = '\0';
  91.     testpoint[X] = (double) atoi(argv[1]);
  92.     testpoint[Y] = (double) atoi(t);
  93.  
  94.     /*
  95.      * if the mapname contains a '/', it represents a unix path -
  96.      * we get the translated path, and skip reading the configuration file.
  97.      */
  98.     if (strchr(mapname,'/')) {
  99.       strcpy(conf,getenv("PATH_TRANSLATED"));
  100.       goto openconf;
  101.     }
  102.     
  103.     if ((fp = fopen(CONF_FILE, "r")) == NULL){
  104.         sprintf(errstr, "Couldn't open configuration file: %s", CONF_FILE);
  105.         servererr(errstr);
  106.     }
  107.  
  108.     while(!(getline(input,MAXLINE,fp))) {
  109.         char confname[MAXLINE];
  110.         if((input[0] == '#') || (!input[0]))
  111.             continue;
  112.         for(i=0;isname(input[i]) && (input[i] != ':');i++)
  113.             confname[i] = input[i];
  114.         confname[i] = '\0';
  115.         if(!strcmp(confname,mapname))
  116.             goto found;
  117.     }
  118.     /*
  119.      * if mapname was not found in the configuration file, it still
  120.      * might represent a file in the server root directory -
  121.      * we get the translated path, and check to see if a file of that
  122.      * name exists, jumping to the opening of the map file if it does.
  123.      */
  124.     if(feof(fp)) {
  125.       struct stat sbuf;
  126.       strcpy(conf,getenv("PATH_TRANSLATED"));
  127.       if (!stat(conf,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG))
  128.     goto openconf;
  129.       else
  130.     servererr("Map not found in configuration file.");
  131.     }
  132.     
  133.   found:
  134.     fclose(fp);
  135.     while(isspace(input[i]) || input[i] == ':') ++i;
  136.  
  137.     for(j=0;input[i] && isname(input[i]);++i,++j)
  138.         conf[j] = input[i];
  139.     conf[j] = '\0';
  140.  
  141.   openconf:
  142.     if(!(fp=fopen(conf,"r"))){
  143.     sprintf(errstr, "Couldn't open configuration file: %s", conf);
  144.         servererr(errstr);
  145.     }
  146.  
  147.     while(!(getline(input,MAXLINE,fp))) {
  148.         char type[MAXLINE];
  149.         char url[MAXLINE];
  150.         char num[10];
  151.  
  152.         if((input[0] == '#') || (!input[0]))
  153.             continue;
  154.  
  155.         type[0] = '\0';url[0] = '\0';
  156.  
  157.         for(i=0;isname(input[i]) && (input[i]);i++)
  158.             type[i] = input[i];
  159.         type[i] = '\0';
  160.  
  161.         while(isspace(input[i])) ++i;
  162.         for(j=0;input[i] && isname(input[i]);++i,++j)
  163.             url[j] = input[i];
  164.         url[j] = '\0';
  165.  
  166.         if(!strcmp(type,"default") && !sawpoint) {
  167.             strcpy(def,url);
  168.             continue;
  169.         }
  170.  
  171.         k=0;
  172.         while (input[i]) {
  173.             while (isspace(input[i]) || input[i] == ',')
  174.                 i++;
  175.             j = 0;
  176.             while (isdigit(input[i]))
  177.                 num[j++] = input[i++];
  178.             num[j] = '\0';
  179.             if (num[0] != '\0')
  180.                 pointarray[k][X] = (double) atoi(num);
  181.             else
  182.                 break;
  183.             while (isspace(input[i]) || input[i] == ',')
  184.                 i++;
  185.             j = 0;
  186.             while (isdigit(input[i]))
  187.                 num[j++] = input[i++];
  188.             num[j] = '\0';
  189.             if (num[0] != '\0')
  190.                 pointarray[k++][Y] = (double) atoi(num);
  191.             else {
  192.                 fclose(fp);
  193.                 servererr("Missing y value.");
  194.             }
  195.         }
  196.         pointarray[k][X] = -1;
  197.         if(!strcmp(type,"poly"))
  198.             if(pointinpoly(testpoint,pointarray))
  199.                 sendmesg(url);
  200.         if(!strcmp(type,"circle"))
  201.             if(pointincircle(testpoint,pointarray))
  202.                 sendmesg(url);
  203.         if(!strcmp(type,"rect"))
  204.             if(pointinrect(testpoint,pointarray))
  205.                 sendmesg(url);
  206.         if(!strcmp(type,"point")) {
  207.         /* Don't need to take square root. */
  208.         dist = ((testpoint[X] - pointarray[0][X])
  209.             * (testpoint[X] - pointarray[0][X]))
  210.            + ((testpoint[Y] - pointarray[0][Y])
  211.               * (testpoint[Y] - pointarray[0][Y]));
  212.         /* If this is the first point, or the nearest, set the default. */
  213.         if ((! sawpoint) || (dist < mindist)) {
  214.         mindist = dist;
  215.             strcpy(def,url);
  216.         }
  217.         sawpoint++;
  218.     }
  219.     }
  220.     if(def[0])
  221.         sendmesg(def);
  222.     servererr("No default specified.");
  223. }
  224.  
  225. sendmesg(char *url)
  226. {
  227.   if (strchr(url, ':'))   /*** It is a full URL ***/
  228.     printf("Location: ");
  229.   else                    /*** It is a virtual URL ***/
  230.     printf("Location: http://%s:%s", getenv("SERVER_NAME"), 
  231.            getenv("SERVER_PORT"));
  232.  
  233.     printf("%s%c%c",url,10,10);
  234.     printf("This document has moved <A HREF=\"%s\">here</A>%c",url,10);
  235.     exit(1);
  236. }
  237.  
  238. int pointinrect(double point[2], double coords[MAXVERTS][2])
  239. {
  240.         return ((point[X] >= coords[0][X] && point[X] <= coords[1][X]) &&
  241.         (point[Y] >= coords[0][Y] && point[Y] <= coords[1][Y]));
  242. }
  243.  
  244. int pointincircle(double point[2], double coords[MAXVERTS][2])
  245. {
  246.         int radius1, radius2;
  247.  
  248.         radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] -
  249.         coords[1][Y])) + ((coords[0][X] - coords[1][X]) * (coords[0][X] -
  250.         coords[1][X]));
  251.         radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y])) +
  252.         ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
  253.         return (radius2 <= radius1);
  254. }
  255.  
  256. int pointinpoly(double point[2], double pgon[MAXVERTS][2])
  257. {
  258.         int i, numverts, inside_flag, xflag0;
  259.         int crossings;
  260.         double *p, *stop;
  261.         double tx, ty, y;
  262.  
  263.         for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++)
  264.                 ;
  265.         numverts = i;
  266.         crossings = 0;
  267.  
  268.         tx = point[X];
  269.         ty = point[Y];
  270.         y = pgon[numverts - 1][Y];
  271.  
  272.         p = (double *) pgon + 1;
  273.         if ((y >= ty) != (*p >= ty)) {
  274.                 if ((xflag0 = (pgon[numverts - 1][X] >= tx)) ==
  275.                 (*(double *) pgon >= tx)) {
  276.                         if (xflag0)
  277.                                 crossings++;
  278.                 }
  279.                 else {
  280.                         crossings += (pgon[numverts - 1][X] - (y - ty) *
  281.                         (*(double *) pgon - pgon[numverts - 1][X]) /
  282.                         (*p - y)) >= tx;
  283.                 }
  284.         }
  285.  
  286.         stop = pgon[numverts];
  287.  
  288.         for (y = *p, p += 2; p < stop; y = *p, p += 2) {
  289.                 if (y >= ty) {
  290.                         while ((p < stop) && (*p >= ty))
  291.                                 p += 2;
  292.                         if (p >= stop)
  293.                                 break;
  294.                         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  295.                                 if (xflag0)
  296.                                         crossings++;
  297.                         }
  298.                         else {
  299.                                 crossings += (*(p - 3) - (*(p - 2) - ty) *
  300.                                 (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  301.                         }
  302.                 }
  303.                 else {
  304.                         while ((p < stop) && (*p < ty))
  305.                                 p += 2;
  306.                         if (p >= stop)
  307.                                 break;
  308.                         if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
  309.                                 if (xflag0)
  310.                                         crossings++;
  311.                         }
  312.                         else {
  313.                                 crossings += (*(p - 3) - (*(p - 2) - ty) *
  314.                                 (*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
  315.                         }
  316.                 }
  317.         }
  318.         inside_flag = crossings & 0x01;
  319.         return (inside_flag);
  320. }
  321.  
  322. servererr(char *msg)
  323. {
  324.     printf("Content-type: text/html%c%c",10,10);
  325.     printf("<title>Mapping Server Error</title>");
  326.     printf("<h1>Mapping Server Error</h1>");
  327.     printf("This server encountered an error:<p>");
  328.     printf("%s", msg);
  329.     exit(-1);
  330. }
  331.  
  332. int isname(char c)
  333. {
  334.         return (!isspace(c));
  335. }
  336.  
  337. int getline(char *s, int n, FILE *f) {
  338.     register int i=0;
  339.  
  340.     while(1) {
  341.         s[i] = (char)fgetc(f);
  342.  
  343.         if(s[i] == CR)
  344.             s[i] = fgetc(f);
  345.  
  346.         if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
  347.             s[i] = '\0';
  348.             return (feof(f) ? 1 : 0);
  349.         }
  350.         ++i;
  351.     }
  352. }
  353.  
  354.